#include <stdio.h>
#include "hal_function.h"
#include "app_button.h"
#include "app_base.h"
#include "app_thread.h"

const static char *TAG = "Button";

AppButton::AppButton()
{
    init_flag = 0;
}

extern "C"
{

ButtonEVT IOButtonFsm(char ioval,IOButtonInfo *butinfo,int time)
{
    ButtonEVT evt;

    evt.type = ButtonType_EMPTY;
    if((ioval != butinfo->last_status))
    {
        butinfo->last_status = ioval;
        if(ioval == BUTTON_PRESS)
        {
             butinfo->timecnt = 0;
        }
        else
        {
            if((butinfo->timecnt >= BUTTON_KEEPTIM_MIN) && 
                (butinfo->timecnt < BUTTON_KEEPTIM_MAX))
            {
                if((butinfo->timecnt >= BUTTON_KEEPTIM_FORSHORT_MIN) && 
                    (butinfo->timecnt <= BUTTON_KEEPTIM_FORSHORT_MAX))
                {
                    butinfo->samplecnt = 0;
                    evt.type = ButtonType_SHORT;
                }
                else if(butinfo->timecnt < BUTTON_KEEPTIM_FORSHORT_MIN)
                {
                    butinfo->samplecnt++;
                    butinfo->samplewait = 0;
                }
                else if(butinfo->timecnt > BUTTON_KEEPTIM_FORLONG_MIN)
                {
                    butinfo->samplecnt = 0;
                    evt.type = ButtonType_LONG;
                }
            }
        }
    }
    else
    {
        butinfo->timecnt += time;
        butinfo->samplewait += time;
        
        if(butinfo->samplewait > BUTTON_KEEPTIM_WAIT_MAX)
        {
            if(butinfo->samplecnt > 1)
            {
                evt.type = ButtonType_CONTINUE;
                evt.val = butinfo->samplecnt;
            }
            butinfo->samplecnt = 0;
        }
    }

    return evt;
}

}



void AppButton::touch_pad_check(int time)
{
    static IOButtonInfo touch_statucs;
    int touchVal = touch_sensor_read();
    touchVal = (touchVal < (touch_sensor_get_init_val()/2))?(BUTTON_PRESS):(BUTTON_RELEASE);
    ButtonEVT evt = IOButtonFsm(touchVal,&touch_statucs,time);

    if(evt.type != ButtonType_EMPTY)
    {
        MessageHandle msg;

        msg.type = MessageType::BUTTON;
        msg.message.button.button = ButtonNum::TOUCH;
        msg.message.button.status = static_cast<ButtonStatus>(evt.type);
        AppThread::sendMessage(&msg);
    }

}


void AppButton::mpu_virtual_button_check(int time)
{
   
}
const HARDWARE_BUTTON_HANDLE key_press_map[]={{GPIO_INPUT_IO_KEY_UP,1},{GPIO_INPUT_IO_KEY_DOWN,0}};
void AppButton::hardware_button_check(int time)
{
    static IOButtonInfo key[sizeof(key_press_map)/sizeof(HARDWARE_BUTTON_HANDLE)];
    int io_status;
    ButtonEVT evt;
    for(int iii=0;iii<(sizeof(key_press_map)/sizeof(HARDWARE_BUTTON_HANDLE));iii++)
    {
        io_status = BUTTON_RELEASE;
        if(gpio_read(key_press_map[iii].io) == key_press_map[iii].press_val)
        {
            io_status = BUTTON_PRESS;
        }

        evt = IOButtonFsm(io_status,&key[iii],time);

        if(evt.type != ButtonType_EMPTY)
        {
            MessageHandle msg;

            msg.type = MessageType::BUTTON;
            msg.message.button.button = (iii == 0)?(ButtonNum::UP):(ButtonNum::DOWN);
            msg.message.button.status = static_cast<ButtonStatus>(evt.type);
            AppThread::sendMessage(&msg);
        }
    }
    
}


ButtonEVT AppButton::getButtonEVT()
{
    ButtonEVT evt;
    return evt;
}

void AppButton::run(int time)
{
    if(!this->init_flag)
    {   
        this->init_flag = 0x55;
        //read the button for first time
        
    }
    else
    {
        //scan the button
        this->touch_pad_check(time);
        this->mpu_virtual_button_check(time);
        this->hardware_button_check(time);
    }
}



